import axios, { AxiosError, type AxiosResponse } from 'axios'
import type { ResultType } from '@/type/type'
import type { Config, Method } from '@/request/config'
import { Code } from '@/request/code'
import { useUserStore } from '@/stores/user'
import { SmUtils } from '@/utils/smUtils'
import { AUTHORITY_KEY, TOKEN_KEY, TOKEN_PREFIX } from '@/constant'
import { refreshTokenApi } from '@/request/api/user'
import { useGlobalLoading } from '@/hooks'
import { isEmpty } from '@/utils'
// 创建axios实例
const service = axios.create({
  // 请求地址
  baseURL: '/api',
  // 超时 180s
  timeout: 1800000,
  headers: {
    'Content-type': 'application/json;charset=utf-8',
    'X-Requested-With': 'XMLHttpRequest'
  }
})

service.interceptors.request.use(
  (config) => {
    // 添加公钥
    config.headers[AUTHORITY_KEY] = SmUtils.keypair.publicKey
    // 添加 token
    config.headers[TOKEN_KEY] = createToken()

    return config
  },
  (error) => {
    console.log(error)
    return Promise.reject(error)
  }
)

service.interceptors.response.use(
  async (response: AxiosResponse<ResultType<any>>) => {
    const originalRequest = response.config
    // token过期，重新获取token再重新请求
    if (response.data.code === Code.AUTH_EXPIRES) {
      await refreshTokenApi(useUserStore().user.id).then((res: ResultType<string>) => {
        if (res.code === Code.SUCCESS) {
          useUserStore().token = res.data
        }
      })
      // 使用相同的配置重试请求
      return new Promise((resolve, reject) => {
        service(originalRequest).then(resolve).catch(reject)
      })
    } else if (response.data.code === Code.NEED_DECRYPTION) {
      const data = SmUtils.deSm2(SmUtils.keypair.privateKey, response.data.data)
      if (data !== '' && data !== undefined) {
        response.data.data = JSON.parse(data)
      }
      response.data.code = Code.SUCCESS
      return response
    } else {
      // 提示信息
      if ('GET' !== response.config.method?.toUpperCase()) {
        response.data.data
          ? ElMessage.success(response.data.msg)
          : ElMessage.error(response.data.msg)
      }
      return response
    }
  },
  (err: AxiosError<any>) => {
    const e: ResultType<any> = {
      code: err.response?.status || 400,
      msg: err.response?.statusText || '服务器异常！',
      data: null
    }
    ElMessage.error('服务器异常！')
    return Promise.reject(e)
  }
)

export const http = <T>(config: Config): Promise<ResultType<T>> => {
  const method: Method = config.method
  let load = null
  if (method !== undefined && method.toLocaleLowerCase() !== 'get') {
    load = useGlobalLoading({
      text: msg.get(method.toLocaleLowerCase() as Method),
      background: 'rgba(50,50,50,0.6)'
    })
  }
  return new Promise<ResultType<T>>((resolve, reject) => {
    service
      .request<ResultType<T>>(config)
      .then((res: AxiosResponse<ResultType<T>>) => {
        load?.close()
        resolve(res.data)
      })
      .catch((err: ResultType<any>) => {
        load?.close()
        reject(err)
      })
  })
}

const createToken = () => {
  const token = localStorage.getItem(TOKEN_KEY)
  if (token !== null && !isEmpty(JSON.parse(token))) {
    return TOKEN_PREFIX + JSON.parse(token).token
  }
  return null
}

const msg = new Map<Method, string>()
msg.set('get', '正在加载数据，请稍等...')
msg.set('post', '正在上传数据，请稍等...')
msg.set('put', '正在上传数据，请稍等...')
msg.set('delete', '正在删除，请稍等...')
